<?php
/**
 * Here the class '\UF\Config\Writer\Xml' is defined.
 *
 * @category   UniKap-Framework
 * @package    Config
 * @subpackage Writer
 * @author     Ulf -UniKado- Kadner <ulfikado@gmail.com>
 * @since      2014-03-29 16:17
 * @version    0.1
 */

namespace UF\Config\Writer
{

    /**
     * A configuration writer, working with XML config files.
     *
     * Each config XML file will contain config elements mit the attributes 'name', 'type' and 'strict'. The values
     * are strored as a element string
     * (<code>&lt;Config name="foo" type="string" strict="0"&gt;The value here&lt;/Config&gt;</code>)
     *
     * @since      v0.1
     */
    class Xml implements \UF\Config\IWriter
    {

        # <editor-fold defaultstate="collapsed" desc="- - - -   P R I V A T E   F I E L D S   - - - - - - - - - - - - - - - - - - - - -">

        private $file;
        private $rootElementName;
        private $configElementName;
        /**
         * @var \UF\Config\IReader
         */
        private $reader;

        # </editor-fold>

        # <editor-fold defaultstate="collapsed" desc="- - - >   C O N S T R U C T O R   - - - - - - - - - - - - - - - - - - - - - - - -">

        /**
         * Inits a new instance.
         *
         * @param  \UF\Config\IReader $reader The reader
         * @param  string $file The Xml config file to write. If its not different from readers file, use NULL value
         * @param  type $rootElementName The name of the root XML element. (Defaults to 'Configs')
         * @param  type $configElementName The name of the config XML elements. (Defaults to 'Config')
         * @throws \UF\ArgumentException If no reader an no file is defined.
         * @throws \UF\IO\FileFormatException
         * @since  v0.1
         */
        public function __construct( \UF\Config\IReader $reader=null,
            $file=null, $rootElementName='Configs', $configElementName='Config')
        {
            $this->reader = $reader;
            if ( \is_null( $reader ) ) {
                if ( empty( $file ) ) { throw new \UF\ArgumentException(
                    'file', $file, 'No file defined to init a XML config writer!' ); }
                $this->reader = new \UF\Config\Reader\Xml( $file, $rootElementName, $configElementName );
                $this->file = $file;
                $this->rootElementName = $rootElementName;
                $this->configElementName = $configElementName;
                return; }
            if ( empty( $file ) )
            {
                $options = $this->reader->getOptions();
                if ( !isset( $options['file'] ) ) { throw new \UF\IO\FileFormatException(
                    $file, 'No file defined to init a XML config writer!' ); }
                $file = $options['file'];
            }
            $this->file = $file;
            $this->rootElementName = $rootElementName;
            $this->configElementName = $configElementName;
        }

        # </editor-fold>

        # <editor-fold defaultstate="collapsed" desc="- - - -   P U B L I C   M E T H O D S   - - - - - - - - - - - - - - - - - - - - -">

        /**
         * Returns if writing is anabled.
         *
         * @return boolean
         * @since  v0.1
         */
        public function canWrite()
        {
            return !empty( $this->file );
        }

        /**
         * Returns all 3 options of th e writer as a associative array. Options are 'file', 'rootElementName'
         * and 'configElementName'.
         *
         * @return array
         * @since  v0.1
         */
        public function getOptions()
        {
            return array(
                'file'              => $this->file,
                'rootElementName'   => $this->rootElementName,
                'configElementName' => $this->configElementName
            );
        }

        /**
         * Returns the associated config reader
         *
         * @return \UF\Config\IReader
         * @since  v0.1
         */
        public function getReader()
        {
            return $this->reader;
        }

        /**
         * Writes all defined config values to current used source.
         *
         * @param  \UF\Config\ValueCollection $configValues All configuration values to write
         * @return boolean
         * @since  v0.1
         */
        public function write( \UF\Config\ValueCollection $configValues )
        {
            $this->reader->reload();
            $currentValues = $this->reader->readAll()->toArray();
            $confValues = $configValues->toArray();
            foreach ( $confValues as $cname => $cvalue ) { $currentValues[$cname] = $cvalue; }
            $w = new \XMLWriter();
            $w->openUri( $this->file );
            $w->setIndent( true ); $w->setIndentString( '  ' );
            $w->startDocument( '1.0', 'utf-8' );
            $w->startElement( $this->rootElementName ); // <Configs>
            foreach ( $currentValues as $value )
            {
                $w->startElement( $this->configElementName ); // <Config ...>
                $w->writeAttribute( 'name', $value->name );
                $w->writeAttribute( 'type', $value->type );
                $w->writeAttribute( 'strict', $value->isstrict ? '1' : '0' );
                $w->text( (string)$value );
                $w->endElement(); // </Config>
            }
            $w->endElement(); // </Configs>
            $w->endDocument(); $w->flush();
        }

        # </editor-fold>

    }

}

